import { BasePlugin } from '../plugin-system/base-plugin.js'
import { createLogger } from '../utils/logger.js'

const logger = createLogger('SyntaxHighlight')
import highlightRules from '../highlight-rules.json'

/**
 * 语法高亮插件
 * 提供代码语法高亮功能
 */
export class SyntaxHighlightPlugin extends BasePlugin {
    constructor(editor, options = {}) {
        super(editor, {
            // 默认配置
            enableHighlighting: true,
            debounceDelay: 100,
            highlightLanguage: 'javascript',
            customRules: [],
            rulesFile: null, // 自定义规则文件路径
            ...options
        })

        // 防抖定时器
        this.highlightTimer = null
        
        // 编译后的规则缓存
        this.compiledRules = new Map()
        
        // 加载高亮规则
        this.loadHighlightRules()
    }

    initialize() {
        // 插件初始化逻辑
        this.loadHighlightRules()
    }

    onEnable() {
        // 监听编辑器事件
        this.editor.on('editor:input', this.handleInput.bind(this))
        this.editor.on('editor:update', this.updateHighlighting.bind(this))
        this.editor.on('editor:scroll', this.syncHighlightScroll.bind(this))

        // 加载高亮规则（如果还未加载）
        if (this.compiledRules.size === 0) {
            this.loadHighlightRules().then(() => {
                // 规则加载完成后立即更新高亮
                this.updateHighlighting()
            })
        } else {
            // 立即更新高亮
            this.updateHighlighting()
        }

        this.emit('syntaxHighlight:enabled')
    }

    onDisable() {
        // 移除事件监听
        this.editor.off('editor:input', this.handleInput.bind(this))
        this.editor.off('editor:update', this.updateHighlighting.bind(this))
        this.editor.off('editor:scroll', this.syncHighlightScroll.bind(this))

        // 清除高亮
        this.clearHighlighting()

        this.emit('syntaxHighlight:disabled')
    }

    onDestroy() {
        if (this.highlightTimer) {
            clearTimeout(this.highlightTimer)
        }
        this.clearHighlighting()
    }

    /**
     * 处理输入事件
     */
    handleInput(data) {
        if (this.options.enableHighlighting) {
            // 如果是撤销/重做操作，立即更新高亮（不使用防抖）
            if (data.isUndo || data.isRedo) {
                this.updateHighlighting()
            } else {
                // 正常输入使用防抖更新
                this.debouncedUpdateHighlighting()
            }
        }
    }

    /**
     * 防抖更新高亮
     */
    debouncedUpdateHighlighting() {
        if (this.highlightTimer) {
            clearTimeout(this.highlightTimer)
        }

        this.highlightTimer = setTimeout(() => {
            this.updateHighlighting()
        }, this.options.debounceDelay)
    }

    /**
     * 更新语法高亮
     */
    updateHighlighting() {
        if (!this.options.enableHighlighting || !this.editor.highlightLayer) {
            return
        }

        const code = this.editor.editor.value || ""


        try {
            // 先清空旧的高亮
            this.editor.highlightLayer.innerHTML = ''
            // 应用语法高亮
            const highlightedCode = this.applySyntaxHighlighting(code)
            this.editor.highlightLayer.innerHTML = highlightedCode
            // 确保滚动同步
            this.syncHighlightScroll()
            this.emit('syntaxHighlight:updated', { code, highlightedCode })
        } catch (error) {
            this.emit('syntaxHighlight:error', { error })
        }
    }

    /**
     * 应用语法高亮
     */
    applySyntaxHighlighting(code) {
        if (this.options.customRules.length > 0) {
            // 使用自定义规则
            return this.applyCustomHighlighting(code)
        } else {
            // 使用从配置文件加载的规则
            return this.applyRuleBasedHighlighting(code)
        }
    }

    /**
     * 应用自定义高亮规则
     */
    applyCustomHighlighting(code) {
        let highlightedCode = code

        // 应用自定义规则
        for (const rule of this.options.customRules) {
            if (rule.regex && rule.className) {
                highlightedCode = this.safeReplace(
                    highlightedCode,
                    rule.regex,
                    (match) => `<span class="${rule.className}">${match}</span>`
                )
            }
        }

        return highlightedCode
    }

    /**
     * 安全替换函数，避免在已高亮区域重复替换
     */
    safeReplace(text, regex, replacer) {
        return text.replace(regex, (match, ...args) => {
            const offset = args[args.length - 2]
            if (this.isPositionInHighlightTag(text, offset)) {
                return match
            }
            return replacer(match, ...args)
        })
    }

    /**
     * 检查指定位置是否在 span 标签内
     */
    isPositionInHighlightTag(text, position) {
        const lastLtIndex = text.lastIndexOf('<', position - 1)
        if (lastLtIndex === -1) return false
        const lookahead = text.substring(lastLtIndex, Math.min(lastLtIndex + 20, text.length))
        return lookahead.startsWith('<span')
    }

    /**
     * 同步高亮层滚动
     */
    syncHighlightScroll(data) {
        if (this.editor.highlightLayer) {
            this.editor.highlightLayer.scrollTop = this.editor.editor.scrollTop
            this.editor.highlightLayer.scrollLeft = this.editor.editor.scrollLeft
        }
    }

    /**
     * 清除高亮
     */
    clearHighlighting() {
        if (this.editor.highlightLayer) {
            this.editor.highlightLayer.innerHTML = ''
        }
    }

    /**
     * 启用高亮
     */
    enableHighlighting() {
        this.options.enableHighlighting = true
        this.updateHighlighting()
        this.emit('syntaxHighlight:highlightingEnabled')
    }

    /**
     * 禁用高亮
     */
    disableHighlighting() {
        this.options.enableHighlighting = false
        this.clearHighlighting()
        this.emit('syntaxHighlight:highlightingDisabled')
    }

    /**
     * 设置高亮语言
     */
    setLanguage(language) {
        this.options.highlightLanguage = language
        this.updateHighlighting()
        this.emit('syntaxHighlight:languageChanged', { language })
    }

    /**
     * 添加自定义高亮规则
     */
    addCustomRule(rule) {
        if (rule.regex && rule.className) {
            this.options.customRules.push(rule)
            this.updateHighlighting()
            this.emit('syntaxHighlight:ruleAdded', { rule })
        }
    }

    /**
     * 移除自定义高亮规则
     */
    removeCustomRule(index) {
        if (index >= 0 && index < this.options.customRules.length) {
            const removedRule = this.options.customRules.splice(index, 1)[0]
            this.updateHighlighting()
            this.emit('syntaxHighlight:ruleRemoved', { rule: removedRule, index })
            return removedRule
        }
        return null
    }

    /**
     * 清除所有自定义规则
     */
    clearCustomRules() {
        this.options.customRules = []
        this.updateHighlighting()
        this.emit('syntaxHighlight:rulesCleared')
    }

    /**
     * 获取当前配置
     */
    getConfig() {
        return {
            enableHighlighting: this.options.enableHighlighting,
            highlightLanguage: this.options.highlightLanguage,
            customRules: [...this.options.customRules],
            debounceDelay: this.options.debounceDelay,
            rulesFile: this.options.rulesFile
        }
    }

    /**
     * 获取支持的语言列表
     */
    getSupportedLanguages() {
        return Array.from(this.compiledRules.keys())
    }

    /**
     * 获取指定语言的规则
     */
    getLanguageRules(language) {
        return this.compiledRules.get(language) || []
    }

    /**
     * 重新加载高亮规则
     */
    async reloadRules(rulesFile = null) {
        if (rulesFile) {
            this.options.rulesFile = rulesFile
        }
        await this.loadHighlightRules()
        this.updateHighlighting()
        this.emit('syntaxHighlight:rulesReloaded')
    }

    /**
     * 设置自定义规则文件
     */
    setRulesFile(rulesFile) {
        this.options.rulesFile = rulesFile
        return this.loadHighlightRules()
    }

    /**
     * 发射事件的便捷方法
     */
    emit(event, data) {
        this.editor.emit(event, data)
    }

    /**
     * 加载高亮规则
     */
    async loadHighlightRules() {
        try {
            let rules
            
            if (this.options.rulesFile) {
                // 从自定义文件加载规则
                const response = await fetch(this.options.rulesFile)
                rules = await response.json()
            } else {
                // 使用内置规则
                rules = highlightRules
            }
            
            // 编译规则
            this.compileRules(rules)
            
            this.emit('syntaxHighlight:rulesLoaded', { rules })
        } catch (error) {
            logger.warn('Failed to load highlight rules:', error)
            this.emit('syntaxHighlight:rulesLoadError', { error })
            // 使用默认的 JavaScript 规则作为后备
            this.useDefaultRules()
        }
    }

    /**
     * 编译规则为正则表达式
     */
    compileRules(rules) {
        this.compiledRules.clear()
        
        for (const [language, languageConfig] of Object.entries(rules)) {
            const compiledLanguageRules = []
            
            // 按优先级排序规则
            const sortedRules = [...languageConfig.rules].sort((a, b) => (a.priority || 0) - (b.priority || 0))
            
            for (const rule of sortedRules) {
                try {
                    const compiledRule = {
                        name: rule.name,
                        description: rule.description,
                        regex: new RegExp(rule.pattern, 'g'),
                        className: rule.className,
                        priority: rule.priority || 0,
                        replacer: rule.replacer || null
                    }
                    compiledLanguageRules.push(compiledRule)
                } catch (error) {
                    logger.warn(`Failed to compile rule ${rule.name} for ${language}:`, error)
                }
            }
            
            this.compiledRules.set(language, compiledLanguageRules)
        }
    }

    /**
     * 使用默认规则作为后备
     */
    useDefaultRules() {
        const defaultRules = {
            javascript: {
                name: "JavaScript",
                rules: [
                    {
                        name: "multiLineComment",
                        pattern: "(\\/\\*[\\s\\S]*?(?:\\*\\/|$))",
                        className: "comment",
                        priority: 1
                    },
                    {
                        name: "singleLineComment",
                        pattern: "(\\/\\/.*)" ,
                        className: "comment",
                        priority: 2
                    },
                    {
                        name: "doubleQuoteString",
                        pattern: "(\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")",
                        className: "string",
                        priority: 3
                    },
                    {
                        name: "singleQuoteString",
                        pattern: "('[^'\\\\]*(?:\\\\.[^'\\\\]*)*')",
                        className: "string",
                        priority: 4
                    },
                    {
                        name: "functionDefinition",
                        pattern: "function\\s+([a-zA-Z_$][0-9a-zA-Z_$]*)",
                        className: "function",
                        priority: 5,
                        replacer: "function <span class=\"function\">$1</span>"
                    },
                    {
                        name: "keywords",
                        pattern: "\\b(if|else|for|while|function|return|var|let|const|class|import|export|async|await)\\b",
                        className: "keyword",
                        priority: 6
                    },
                    {
                        name: "numbers",
                        pattern: "\\b(\\d+(?:\\.\\d+)?)\\b",
                        className: "number",
                        priority: 7
                    }
                ]
            }
        }
        
        this.compileRules(defaultRules)
    }

    /**
     * 应用基于规则的语法高亮
     */
    applyRuleBasedHighlighting(code) {
        if (!code) return ''

        const language = this.options.highlightLanguage
        const rules = this.compiledRules.get(language)
        
        if (!rules || rules.length === 0) {
            // 如果没有找到规则，返回原代码
            return code
        }

        let highlightedCode = code

        // 按优先级应用规则
        for (const rule of rules) {
            if (rule.replacer) {
                // 使用自定义替换器
                highlightedCode = this.safeReplace(
                    highlightedCode,
                    rule.regex,
                    (...args) => {
                        const match = args[0]
                        return rule.replacer.replace(/\$1/g, args[1] || match)
                    }
                )
            } else {
                // 使用默认的 span 包装
                highlightedCode = this.safeReplace(
                    highlightedCode,
                    rule.regex,
                    match => `<span class="${rule.className}">${match}</span>`
                )
            }
            
            // 重置正则表达式的 lastIndex
            rule.regex.lastIndex = 0
        }

        return highlightedCode
    }

    /**
     * 应用默认语法高亮
     */
    applyDefaultHighlighting(code) {
        if (!code) return ''

        let highlightedCode = code

        // 1. 多行注释
        highlightedCode = this.safeReplace(
            highlightedCode,
            /(\/\*[\s\S]*?(?:\*\/|$))/g,
            match => `<span class="comment">${match}</span>`
        )

        // 2. 单行注释
        highlightedCode = this.safeReplace(
            highlightedCode,
            /(\/\/.*)/g,
            match => `<span class="comment">${match}</span>`
        )

        // 3. 双引号字符串
        highlightedCode = this.safeReplace(
            highlightedCode,
            /("[^"\\]*(?:\\.[^"\\]*)*")/g,
            match => `<span class="string">${match}</span>`
        )

        // 4. 单引号字符串
        highlightedCode = this.safeReplace(
            highlightedCode,
            /('[^'\\]*(?:\\.[^'\\]*)*')/g,
            match => `<span class="string">${match}</span>`
        )

        // 5. 函数定义 - 必须在关键词之前处理，避免 function 被关键词规则覆盖
        highlightedCode = this.safeReplace(
            highlightedCode,
            /function\s+([a-zA-Z_$][0-9a-zA-Z_$]*)/g,
            (match, funcName) => `function <span class="function">${funcName}</span>`
        )

        // 6. 关键字（在函数处理之后，避免冲突）
        highlightedCode = this.safeReplace(
            highlightedCode,
            KEYWORD_REGEX,
            match => `<span class="keyword">${match}</span>`
        )

        // 7. 数字（整数或浮点数）
        highlightedCode = this.safeReplace(
            highlightedCode,
            /\b(\d+(?:\.\d+)?)\b/g,
            match => `<span class="number">${match}</span>`
        )

        return highlightedCode
    }
}